Skip to content

PoC: Crud skill test 01 product#1344

Draft
manuelblum wants to merge 12 commits intomainfrom
crud-skill-test-01-product
Draft

PoC: Crud skill test 01 product#1344
manuelblum wants to merge 12 commits intomainfrom
crud-skill-test-01-product

Conversation

@manuelblum
Copy link
Contributor

Sample PR showcasing how Claude (Opus 4.6) implements full-stack CRUD from a spec file using Comet skills. The entire implementation — API, admin UI, enums, validations — was generated from specs/product/01-product.md.

What's implemented

Area Features
API Entity Scoped Product entity (domain + language) with all fields, MikroORM migration, NestJS module registration
API Resolver & Service Full CRUD (create, update, delete, list, findById, findBySlug), server-side slug/SKU uniqueness validation with typed ProductValidationErrorCode enum
Translatable Enums ProductStatus (Draft, InReview, Published, Archived) and ProductType (Physical, Digital, Subscription) — each with translatable component, chip, editable chip, and SelectField
DataGrid Columns: thumbnail, name, SKU, productType (editable chip), price, productStatus (editable chip), publishedAt, isPublished. Search by name/SKU, filter by status/type, Excel export (image excluded)
Form Four FieldSets (General, Details, Publishing, Media). Client-side validators for price (positive), SKU (format), slug (valid characters). Server-side uniqueness errors shown as inline field errors
Pages StackSwitch with grid/add/edit pages, entity toolbar with product name + SKU support text, ContentScopeIndicator
MasterMenu Route entry with Tag icon at /products

Spec

See specs/product/01-product.md for the full requirements.

Header Header
Datagrid sorting / filtering Screen Recording 2026-03-16 at 07 02 09
Form with client and server validation Screen Recording 2026-03-16 at 07 09 02
Editable Enum Chip in Grid Screen Recording 2026-03-16 at 07 10 16

@manuelblum manuelblum changed the title PoC: comet crud skill test 01 product PoC: Crud skill test 01 product Mar 16, 2026
Comment on lines +67 to +73
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", width: "100%", height: "100%", py: 0.5 }}>
<img
src={damFile.fileUrl}
alt=""
style={{ maxHeight: "100%", maxWidth: "100%", objectFit: "contain", borderRadius: 4 }}
/>
</Box>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +78 to +84
@Property({ type: "text" })
@Field()
domain: string;

@Property({ type: "text" })
@Field()
language: string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally we use an embeddable scope for this.

Comment on lines +73 to +76
@RootBlock(DamImageBlock)
@Property({ type: new RootBlockType(DamImageBlock), nullable: true })
@Field(() => RootBlockDataScalar(DamImageBlock), { nullable: true })
mainImage?: BlockDataInterface;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not every factory in Comet supports nullable blocks. Should blocks always be required? This would be okay because we'll always have a default value.


@Module({
imports: [MikroOrmModule.forFeature([Product])],
providers: [ProductsService, ProductResolver],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now is the time to fix this singular/plural issue. 😁

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the spec in the repo is awesome. 👌🏼

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants